// ============================================================================
//
// Copyright (C) 2006-2007 Dengues
//
// Google Group: http://groups.google.com/group/dengues
// QQ Group: 24885404
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ============================================================================
package org.dengues.designer.ui.editors.palette;

import java.util.Collections;
import java.util.Comparator;
import java.util.Hashtable;
import java.util.List;

import org.dengues.commons.IDenguesSharedImage;
import org.dengues.commons.utils.ImageUtil;
import org.dengues.core.components.IComponentsFactory;
import org.dengues.core.components.IXMLComponent;
import org.dengues.designer.ui.i18n.Messages;
import org.dengues.designer.ui.process.models.CompBlock;
import org.dengues.designer.ui.process.models.CompNote;
import org.eclipse.gef.palette.CombinedTemplateCreationEntry;
import org.eclipse.gef.palette.CreationToolEntry;
import org.eclipse.gef.palette.PaletteDrawer;
import org.eclipse.gef.palette.PaletteEntry;
import org.eclipse.gef.palette.PaletteGroup;
import org.eclipse.gef.palette.PaletteRoot;
import org.eclipse.gef.palette.PanningSelectionToolEntry;
import org.eclipse.gef.palette.ToolEntry;
import org.eclipse.gef.requests.CreationFactory;
import org.eclipse.jface.resource.ImageDescriptor;

/**
 * Qiang.Zhang.Adolf@gmail.com class global comment. Detailled comment <br/>
 * 
 * $Id: Dengues.epf Qiang.Zhang.Adolf@gmail.com 2008-1-23 qiang.zhang $
 * 
 */
public class CompEditorPaletteFactory {

    private static PaletteRoot palette;

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "create".
     * 
     * @param factory
     * @return
     */
    public static PaletteRoot create(IComponentsFactory factory) {
        palette = new PaletteRoot();
        palette.add(createToolsGroup());
        createGenericComponentsDrawer();
        createComponentsDrawer(factory);
        return palette;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "createGenericComponentsDrawer".
     */
    private static void createGenericComponentsDrawer() {
        PaletteDrawer genericDrawer = new CompPaletteDrawer(Messages.getString("CompEditorPaletteFactory.generic")); //$NON-NLS-1$
        CombinedTemplateCreationEntry component = new CombinedTemplateCreationEntry(
                Messages.getString("CompEditorPaletteFactory.blockName"), Messages.getString("CompEditorPaletteFactory.block"), CompNote.class, //$NON-NLS-1$//$NON-NLS-2$
                new CreationFactory() {

                    public Object getNewObject() {
                        return new CompBlock();
                    }

                    public Object getObjectType() {
                        return CompBlock.class;
                    }

                }, ImageUtil.getDescriptor(IDenguesSharedImage.PALETTE_BLOCK), ImageUtil
                        .getDescriptor(IDenguesSharedImage.PALETTE_BLOCK24));
        genericDrawer.add(component);
        component.setDescription(Messages.getString("CompEditorPaletteFactory.blockDesc")); //$NON-NLS-1$
        palette.add(genericDrawer);
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "createComponentsDrawer".
     * 
     * @param factory
     */
    private static void createComponentsDrawer(IComponentsFactory factory) {
        List<IXMLComponent> components = factory.getComponents();
        CombinedTemplateCreationEntry component;

        Hashtable<String, PaletteDrawer> ht = new Hashtable<String, PaletteDrawer>();

        Collections.sort(components, new Comparator<IXMLComponent>() {

            public int compare(IXMLComponent o1, IXMLComponent o2) {
                return o1.getCategory().compareTo(o2.getCategory());
            }
        });

        for (IXMLComponent xmlComponent : components) {
            if (xmlComponent.isLoaded()) {
                String category = xmlComponent.getCategory();
                PaletteDrawer compDrawer = ht.get(category);
                if (compDrawer == null) {
                    compDrawer = createComponentDrawer(ht, category);
                }
                createComponentEntry(compDrawer, xmlComponent);
            }
        }
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "createComponentDrawer".
     * 
     * @param ht
     * @param category
     * @return
     */
    private static PaletteDrawer createComponentDrawer(Hashtable<String, PaletteDrawer> ht, String category) {
        int index = category.indexOf(IXMLComponent.CATEGORY_SEPARATOR);
        String family;
        PaletteDrawer parentPaletteDrawer = null;
        if (index > -1) {
            family = category.substring(index + 1);
            String parentCate = category.substring(0, index);
            parentPaletteDrawer = ht.get(parentCate);
            if (parentPaletteDrawer == null) {
                parentPaletteDrawer = createComponentDrawer(ht, parentCate);
            }
        } else {
            family = category;
        }
        PaletteDrawer paletteDrawer = new CompPaletteDrawer(family);
        paletteDrawer.setInitialState(PaletteDrawer.INITIAL_STATE_CLOSED);
        if (parentPaletteDrawer == null) {
            palette.add(paletteDrawer);
        } else {
            parentPaletteDrawer.add(paletteDrawer);
        }
        ht.put(category, paletteDrawer);
        return paletteDrawer;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "createComponentEntry".
     * 
     * @param compDrawer
     * @param xmlComponent
     */
    private static void createComponentEntry(PaletteDrawer compDrawer, IXMLComponent xmlComponent) {
        CombinedTemplateCreationEntry component;
        String displayName = xmlComponent.getDisplayName();
        String longName = xmlComponent.getLongName();
        ImageDescriptor imageSmall = xmlComponent.getIcon16();
        ImageDescriptor imageLarge = xmlComponent.getIcon24();
        component = new CombinedTemplateCreationEntry(displayName, displayName, CompNote.class, new PaletteComponentFactory(
                xmlComponent), imageSmall, imageLarge);
        component.setDescription(longName);
        compDrawer.add(component);
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "createToolsGroup".
     * 
     * @return
     */
    private static PaletteEntry createToolsGroup() {
        PaletteGroup group = new PaletteGroup("Components"); //$NON-NLS-1$
        ToolEntry tool = new PanningSelectionToolEntry();
        group.add(tool);
        palette.setDefaultEntry(tool);
        CreationToolEntry noteCreationToolEntry = new CreationToolEntry(
                Messages.getString("CompEditorPaletteFactory.note"), Messages.getString("CompEditorPaletteFactory.noteComment"), new CreationFactory() { //$NON-NLS-1$ //$NON-NLS-2$

                    public Object getNewObject() {
                        return new CompNote();
                    }

                    public Object getObjectType() {
                        return CompNote.class;
                    }

                }, ImageUtil.getDescriptor(IDenguesSharedImage.PALETTE_CODE), ImageUtil
                        .getDescriptor(IDenguesSharedImage.PALETTE_CODE));
        group.add(noteCreationToolEntry);
        return group;
    }
}
